import { Injectable } from '@nestjs/common';
import { and, eq, inArray, sql } from 'drizzle-orm';
import { DrizzleService } from '../../db/drizzle.service';
import { menus, roleMenus } from '../../db/schema';
import { CreateMenuDto, UpdateMenuDto } from './dto/menu.schema';

@Injectable()
export class MenuService {
  constructor(private readonly drizzle: DrizzleService) { }

  async create(menu: CreateMenuDto) {
    return await this.drizzle.db.insert(menus).values(menu);
  }

  async findAll() {
    return await this.drizzle.db.select().from(menus)
      .where(eq(menus.delFlag, '0'));
  }

  async findOne(id: number) {
    return await this.drizzle.db
      .select()
      .from(menus)
      .where(and(
        eq(menus.menuId, id),
        eq(menus.delFlag, '0')
      ));
  }

  async update(id: number, menu: UpdateMenuDto) {
    return await this.drizzle.db
      .update(menus)
      .set(menu)
      .where(and(
        eq(menus.menuId, id),
        eq(menus.delFlag, '0')
      ));
  }

  async remove(id: number) {
    // 使用逻辑删除
    return await this.drizzle.db
      .update(menus)
      .set({ delFlag: '1' })
      .where(eq(menus.menuId, id));
  }

  // 获取菜单树形结构
  async getMenuTree() {
    const allMenus = await this.drizzle.db.select().from(menus)
      .where(and(
        eq(menus.delFlag, '0'),
        eq(menus.status, '0')
      ));

    // 递归构建树形结构
    const buildTreeData = (items: any[], parentId = 0) => {
      return items
        .filter(item => item.parentId === parentId)
        .map(item => ({
          ...item,
          children: buildTreeData(items, item.menuId),
        }))
        .sort((a, b) => a.orderNum - b.orderNum);
    };

    return buildTreeData(allMenus);
  }

  // 根据角色ID查询菜单列表
  async getMenuListByRoleId(roleId: number) {
    return await this.drizzle.db
      .select()
      .from(menus)
      .innerJoin(roleMenus, eq(menus.menuId, roleMenus.menuId))
      .where(and(
        eq(roleMenus.roleId, roleId),
        eq(menus.delFlag, '0'),
        eq(menus.status, '0')
      ));
  }

  /**
   * 根据角色ID列表获取授权的菜单按钮权限
   * 直接从菜单表中获取权限标识，不查询sys_permission表
   */
  async getAuthorizedMenuButtonsByRoleIds(roleIds: number[]) {
    if (!roleIds || roleIds.length === 0) {
      return [];
    }

    // 获取角色关联的所有菜单
    const roleMenusList = await this.drizzle.db
      .select({
        menuId: roleMenus.menuId
      })
      .from(roleMenus)
      .where(inArray(roleMenus.roleId, roleIds));

    const menuIds = roleMenusList.map(rm => rm.menuId);
    
    if (menuIds.length === 0) {
      return [];
    }

    // 获取菜单按钮类型的菜单（menuType='F'）及其权限标识
    return await this.drizzle.db
      .select({
        menuId: menus.menuId,
        menuName: menus.menuName,
        menuType: menus.menuType,
        perms: menus.perms,
        parentId: menus.parentId,
        orderNum: menus.orderNum,
        status: menus.status
      })
      .from(menus)
      .where(and(
        inArray(menus.menuId, menuIds),
        eq(menus.delFlag, '0'),
        eq(menus.status, '0'),
        eq(menus.menuType, 'F'), // 只获取按钮类型的菜单
        sql`${menus.perms} != ''` // 只获取有权限标识的菜单
      ));
  }

  /**
   * 获取用户的所有授权菜单权限标识
   * 直接返回权限字符串数组，用于前端权限控制
   */
  async getUserPermissionKeysByRoleIds(roleIds: number[]): Promise<string[]> {
    if (!roleIds || roleIds.length === 0) {
      return [];
    }

    // 获取角色关联的所有菜单权限标识
    const menuPerms = await this.drizzle.db
      .select({
        perms: menus.perms
      })
      .from(menus)
      .innerJoin(roleMenus, eq(menus.menuId, roleMenus.menuId))
      .where(and(
        inArray(roleMenus.roleId, roleIds),
        eq(menus.delFlag, '0'),
        eq(menus.status, '0'),
        sql`${menus.perms} != ''` // 只获取有权限标识的菜单
      ));

    // 过滤空值、null、undefined和空字符串，并去重
    return [...new Set(menuPerms.map(mp => mp.perms).filter((perm): perm is string => typeof perm === 'string' && perm.trim() !== ''))] as string[];
  }
}